package com.breeze.blockchain.common.config;

import com.breeze.blockchain.auth.AuthContextHolder;
import com.breeze.blockchain.common.config.id.SnowIdGenerator;
import com.breeze.components.core.util.web.RequestContextUtil;
import com.breeze.components.mybatis.base.BaseEntity;
import com.breeze.components.web.config.ApplicationConfig;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.AuditMessage;
import com.mybatisflex.core.keygen.KeyGeneratorFactory;
import com.mybatisflex.spring.boot.MyBatisFlexCustomizer;
import java.time.LocalDateTime;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Mybatis flex配置
 *
 * @author breeze
 */
@Configuration
@EnableTransactionManagement
@Slf4j
public class MyBatisFlexGlobalConfig implements MyBatisFlexCustomizer {

  @Bean
  public DataSourceTransactionManager transactionManager(DataSource dataSource) {
    DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
    transactionManager.setDataSource(dataSource);
    return transactionManager;
  }

  @Override
  public void customize(FlexGlobalConfig flexGlobalConfig) {
    // 注册雪花id主键生成器
    KeyGeneratorFactory.register("snowIdGenerator", new SnowIdGenerator());
    // 开启审计功能
    AuditManager.setAuditEnable(true);
    // 设置审计内容
    AuditManager.setMessageFactory(
        () -> {
          AuditMessage message = new AuditMessage();
          message.setModule(ApplicationConfig.getAppId());
          message.setUrl(RequestContextUtil.getRequestUrl());
          message.setHostIp(RequestContextUtil.getClientIp());
          return message;
        });
    // 设置 SQL 审计收集器
    AuditManager.setMessageCollector(
        auditMessage -> {
          String sql = auditMessage.getFullSql();
          if (sql.contains("distributed_lock") || sql.contains("secure_invoke_json")) {
            return;
          }
          log.info(
              "Flex exec sql >>> app:{},ip:{},url:{},sql:{},took:{}ms",
              auditMessage.getModule(),
              auditMessage.getHostIp(),
              auditMessage.getUrl(),
              auditMessage.getFullSql(),
              auditMessage.getElapsedTime());
        });
    // 全局配置监听器
    flexGlobalConfig.registerInsertListener(
        entity -> {
          BaseEntity account = (BaseEntity) entity;
          account.setCreateBy(AuthContextHolder.mybatisGetUserId());
          account.setCreateTime(LocalDateTime.now());
          account.setUpdateBy(AuthContextHolder.mybatisGetUserId());
          account.setUpdateTime(LocalDateTime.now());
          account.setDeleteFlag(0);
        },
        BaseEntity.class);
    flexGlobalConfig.registerUpdateListener(
        entity -> {
          BaseEntity account = (BaseEntity) entity;
          account.setUpdateBy(AuthContextHolder.mybatisGetUserId());
          account.setUpdateTime(LocalDateTime.now());
        },
        BaseEntity.class);
  }
}
